-- check if actor is enemy to a specific faction (p[1]] function is_actor_enemy_to_faction(actor,npc,p) if(p[1]~=nil) then return game_relations.is_factions_enemies(character_community(db.actor), p[1]) end return false end function is_npc_enemy_to_faction(actor,npc,p) if (p[1]~=nil) and npc then return game_relations.is_factions_enemies(character_community(npc), p[1]) end return false end function toolkit_task_done(actor, npc, p) if (not p and p[1]) then return end local npc_sec = npc and npc:section() if npc_sec and has_alife_info(npc_sec .. "_upgrade_tier_" .. tostring(p[1])) then return true end return false end function drugkit_task_done(actor, npc, p) local npc_sec = npc and npc:section() if npc_sec and has_alife_info(npc_sec .. "_drugkit_done") then return true end return false end function is_actor_from_faction(actor, npc, p) local comm = db.actor and character_community(db.actor):sub(7) for k,v in pairs (p) do --printf("actor community: [%s], needed community: [%s]", comm, v) if (v == comm) then return true end end return false end -------------------------- -- Warfare -------------------------- function is_warfare(actor, npc) return (_G.WARFARE == true) end function check_npc_trader(actor, npc, p) if npc and npc:name() and string.find(npc:name(),"sim_default_%a+_trader") then return true end return false end function check_npc_mechanic(actor, npc, p) if npc and npc:name() and string.find(npc:name(),"sim_default_%a+_mechanic") then return true end return false end function check_npc_medic(actor, npc, p) if npc and npc:name() and string.find(npc:name(),"sim_default_%a+_medic") then return true end return false end function check_npc_barman(actor, npc, p) if npc and npc:name() and string.find(npc:name(),"sim_default_%a+_barman") then return true end return false end --mlr function if_actor_great(actor, npc) local rank = ranks.get_obj_rank_name(actor) if (rank == "veteran" or rank == "expert" or rank == "master" or rank == "legend") then return true else return false end end function if_actor_powerful(actor, npc) local repu = actor:character_reputation() if (repu >= 999) then return true else return false end end function if_actor_not_powerful(actor, npc) local repu = actor:character_reputation() if (repu <= 999) then return true else return false end end function in_debt(actor,npc,p) if mlr_utils.load_var("debt_" .. tostring(npc:id())) then return true end return false end --g0dl1ke function if_hip_veteran(actor, npc) local rank = ranks.get_obj_rank_name(npc) return (rank == "veteran" or rank == "expert" or rank == "master" or rank == "legend") end function request_to_hip_task(actor) local rank = ranks.get_obj_rank_name(actor) return (rank == "experienced" or rank == "professional" or rank == "veteran" or rank == "expert" or rank == "master" or rank == "legend") end --g0dl1ke function actor_has_active_item(actor, npc) if db.actor and (db.actor:active_item() or db.actor:active_detector()) then return true end return false end function actor_has_target_obj(actor, npc) return level.get_target_obj() and true or false end -- Created by DoctorX -- Description: Checks if a faction is an enemy of the player's faction -- Usage: drx_sl_is_enemy( p[1] ) -- Parameters: p[1] (type:string) -- - Faction to check is enemy of player (stalker, dolg, freedom, csky, ecolog, killer, army, bandit, monolith, or actor_(faction)) -- Return value (type: bool): Returns true if the faction is an enemy of the player faction, false otherwise -- Check if faction is enemy of player: function drx_sl_is_enemy( actor, npc, p ) if ( p[1] ~= nil ) then return relation_registry.community_relation( p[1], alife( ):actor( ):community( ) ) <= -1000 else return false end end -- \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ --[[ modified by Alundaio (original: ???? GSC) Copyright (C) 2012 Alundaio This program is free software; you can redistribute and/or modify it under the terms of the Open S.T.A.L.K.E.R. Mod License version 1.0. -]] -- TODO: Remove all unused COP story functions -- Modified by DoctorX -- Description: -- - Provides a random chance whether a task will be available -- Usage: random_chance( p[1] ) -- Parameters: -- p[1] (type: int) Percent chance the task will be given -- Return value (type: bool): Returns true if a task can be given, false otherwise -- Decide if task should be available: function random_chance( actor, npc, p ) local r = p and p[1] and tonumber( p[1] ) or 50 if ( math.random( 1, 100 ) <= r ) then return true end return false end -- checks if a task has stage of equal value -- param 1 - task_id -- param 2 - value function check_task_stage(actor,npc,p) local tm = task_manager.get_task_manager() local task_info = tm.task_info if (task_info[p[1]] and task_info[p[1]].stage == tonumber(p[2])) then --printf("p[1] = %s stage=%s",p[1],p[2]) return true end return false end function is_bounty(actor,npc,p) local id = npc:id() for task_id,npc_id in pairs(axr_task_manager.bounties_by_id) do if (npc_id == id) then return true end end return false end function npc_not_actor(actor,npc,p) return npc:id() ~= 0 or false end function dist_to_task_target_anomaly_le(actor,npc,p) local d = p[1] if not (d) then return false end local name = db.actor and load_var(db.actor,"task_target_anomaly") if not (name) then return false end local anomaly = db.anomaly_by_name[name] if not (anomaly and anomaly.object) then return false end return heli_alife.distance_2d_sqr(npc:position(),anomaly.object:position()) <= tonumber(d)^2 end function has_task_target_anomaly(actor,npc,p) if _G.WARFARE then return db.actor and load_var(db.actor,"task_target_anomaly_analyzed") == "not_analyzed" --xQd end return db.actor and load_var(db.actor,"task_target_anomaly") ~= nil end function actor_has_companion_slot(actor,npc,p) return db.actor and load_var(db.actor,p[1] or "task_companion_slot_1") == nil end --param 1 dist --param 2 smart_name (optional) function check_nearest_smart_dist_le(actor,npc,p) if (smart_terrain.nearest_to_actor_smart.id and smart_terrain.nearest_to_actor_smart.dist > tonumber(p[1])) then return false end local smart = p[2] and SIMBOARD.smarts_by_names[p[2]] if (smart and smart_terrain.nearest_to_actor_smart.id and smart.id == smart_terrain.nearest_to_actor_smart.id) then return true end return false end function check_smart_dist_le(actor,npc,p) local smart = p[2] and SIMBOARD.smarts_by_names[p[2]] if (smart and smart.position:distance_to(npc:position()) <= (tonumber(p[1]) or 0)) then return true end return false end ----------------------- -- Task ----------------------- function has_task(actor,npc,p) local task_info = p[1] and task_manager.get_task_manager().task_info[p[1]] if not (task_info) then return false end return p[2] == nil or task_info.status == p[2] end function has_task_on_stage(actor,npc,p) local task_info = p[1] and task_manager.get_task_manager().task_info[p[1]] if not (task_info) then return false end return task_info.stage == (tonumber(p[2] or 0) or 0) end function has_task_not_completed(actor,npc,p) local task_info = p[1] and task_manager.get_task_manager().task_info[p[1]] if not (task_info) then return false end return task_info.status ~= "completed" and task_info.status ~= "fail" end function has_completed_task_prerequisites(actor,npc,p) if not (p[1]) then return true end local precond = task_manager.task_ini:r_string_ex(p[1],"precondition") if (precond and precond ~= "") then precond = xr_logic.parse_condlist(npc, p[1], "precondition", task_manager.task_ini:r_string_ex(p[1],"precondition") or "true") if (precond == "false") then return false end if (db.actor and xr_logic.pick_section_from_condlist(db.actor, npc, precond) == "false") then return false end end local prereq = task_manager.task_ini:r_string_ex(p[1],"prerequisites") if (prereq == nil or prereq == "") then return true end local tm = task_manager.get_task_manager() local info = tm.task_info if (info[p[1]]) then -- HAS TASK ALREADY! return false end prereq = str_explode(prereq,",") local tsk for i=1,#prereq do tsk = prereq[i] if not (info[tsk]) then --printf("no tsk %s",tsk) return false end if (info[tsk].status ~= "completed" and info[tsk].status ~= "fail") then --printf("task %s not completed %s",task,info[tsk].status) return false end end return true end function has_given_task(actor,npc,p) -- xQd, there are duplicate assassination, find the artefact, etc task for loners, bandits, etc. We don't want the same trader to give the same task, so we add this function at the precondition of the task to check if the npc has already given a similar task local task_id = p and p[1] local talking_npc = mob_trade.GetTalkingNpc() if not talking_npc then printf("couldnt find talking npc") end if task_id and talking_npc then local task_info = task_manager.get_task_manager().task_info for k,v in pairs(task_info) do if (k == task_id and v.task_giver_id and v.task_giver_id == talking_npc:id()) then return true end end end return false end function dist_to_lvid_ge(actor,npc,p) local vid = tonumber(p[1]) if not (vid) then return false end local position = level.vertex_position(vid) if (npc:position():distance_to_sqr(position) >= tonumber(p[2])) then return true end return false end function dist_to_job_point_le(actor, npc, p) if not (npc) then return false end local smart = xr_gulag.get_npc_smart(npc) if smart == nil then return false end local npc_info = smart.npc_info[npc:id()] if npc_info then local npc_job = npc_info.job if (npc_job) then local alife_task = npc_job.alife_task if alife_task then return npc:position():distance_to_sqr(alife_task:position()) <= p[1]*p[1] end end end return false end function sim_avail(actor,npc,p) local smart = p[1] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end return simulation_objects.available_by_id[smart.id] == true end -- param 1 = smart -- param 2 = section logic (omit 'logic@') -- param 3 = distance function dist_to_obj_on_job_le(actor,npc,p) if not (npc) then return false end local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end local obj = smart and smart.npc_by_job_section["logic@"..p[2]] obj = obj and (db.storage[obj] and db.storage[obj].object or level.object_by_id(obj)) if not (obj) then return false end return npc:position():distance_to_sqr(obj:position()) <= tonumber(p[3])^2 end function dist_to_job_point_ge(actor, npc, p) if not (npc) then return false end local smart = xr_gulag.get_npc_smart(npc) if smart == nil then return false end local npc_info = smart.npc_info[npc:id()] if npc_info then local npc_job = npc_info.job if (npc_job) then local alife_task = npc_job.alife_task if alife_task then return npc:position():distance_to_sqr(alife_task:position()) >= p[1]*p[1] end end end return false end -- Каждая функция в этом файле используется как условие xr_logic: {=функция !функция} -- Если в функцию необходимо передавать параметры, то: {=функция(парам1:парам2:...) !функция(парам1:парам2:...)} -- Формат: function f(actor, npc). В случае передачи параметров: function f(actor, npc, p). -- ---------------------------------------------------------------------------------------------------- -- Functions for working specifically with combat_ignore_cond -- ---------------------------------------------------------------------------------------------------- -- Match name against all given params (ex. {=check_enemy_name(name1:name2:name3:name4)}) function check_enemy_name (enemy , npc , p) local name if enemy and enemy:alive() then name = enemy:name() for i, v in pairs(p) do if string.find( name, v ) ~= nil then return true end end end return false end function is_enemy_fighting_actor(enemy,npc) if (enemy:alive() and xr_combat_ignore.fighting_with_actor_npcs[enemy:id()]) then return true end return false end function is_enemy_actor(enemy, npc) return enemy:id() == AC_ID end function is_enemy_actor_or_companion(enemy,npc) if (IsMonster(enemy)) then return false end if not (npc:relation(enemy) >= game_object.enemy) then return false end local id = enemy:id() if (id == AC_ID) then return true end if (alife():has_info(id,"npcx_is_companion")) then return true end return false end -- current enemy at a distance greater than or equal to the specified Distance -- для combat_ignore -- param 1 - distance^2 function fighting_dist_ge(enemy, npc, p) p[1] = p[1] and tonumber(p[1]) return p[1] and enemy:alive() and enemy:position():distance_to_sqr(npc:position()) >= p[1]^2 or false end -- param 1 - distance^2 function fighting_dist_le(enemy, npc, p) p[1] = p[1] and tonumber(p[1]) return p[1] and enemy:alive() and enemy:position():distance_to_sqr(npc:position()) <= p[1]^2 or false end -- param 1 zone name function enemy_in_zone(enemy, npc, p) return utils_obj.npc_in_zone(enemy, p[1]) or false end -- param 1 - Community to match function is_enemy_community(enemy,npc,p) return enemy:alive() and character_community(enemy) == p[1] end -- Check for membership to one of the enemy groups (simboard.group_id_by_levels) -- Each Squad spawned is given a group id according to level -- All squads on a certain level will have matching level group ids -- (You can check more than one) function enemy_group(enemy, npc, p) if not (enemy:alive()) then return false end local g = enemy:group() for i, v in pairs(p) do if v == g then --printf("_bp: [%s]'s enemy is from group [%d]", npc:name(), v) return true end end return false end -- see above function is_enemy_same_group(actor,npc) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) if (not enemy:alive()) then return false end return enemy:group() == npc:group() end ------------------------------- -- Conditions for enemies before combat_ignore_cond is checked ------------------------------- function see_pure_enemy(actor,npc) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) return enemy and enemy:alive() and npc:see(enemy) or false end function pure_enemy_dist_le(actor,npc,p) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) return enemy and enemy:alive() and enemy:position():distance_to_sqr(npc:position()) <= p[1]^2 or false end -- Returns true if a NPC's pure enemy (before ignore_cond) occupies a job by section for a given smart -- param 1 is the job section (ie. "logic@walker1") -- param 2 is the smart name. If it's empty it will default to calling NPC's smart function is_enemy_on_job(actor, npc, p) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) if (enemy == nil or not enemy:alive()) then return false end local smart if p and p[2] then smart = SIMBOARD:get_smart_by_name(p[2]) else smart = xr_gulag.get_npc_smart(enemy) end if smart == nil then return false end for id,npc_info in pairs(smart.npc_info) do if (npc_info.job and npc_info.job.section == p[1]) then return true end end return false end -- Returns true if enemy's smart equals the given smart -- param 1 is the smart name function enemy_smart(actor, npc, p) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) if (enemy == nil or not enemy:alive()) then return false end local smart = xr_gulag.get_npc_smart(enemy) if not (smart) then return false end return p and smart:name() == p[1] end function has_pure_enemy(actor, npc) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) return enemy and enemy:alive() or false end -- param 1 - Enemy's Time-in-memory less_than_equal_to function pure_enemy_mem_time_le(actor, npc, p) local st = db.storage[npc:id()] local enemy = st and st.enemy_id and (db.storage[st.enemy_id] and db.storage[st.enemy_id].object or level.object_by_id(st.enemy_id)) return p and p[1] and enemy and enemy:alive() and npc:memory_time(enemy) <= tonumber(p[1]) or false end -- ---------------------------------------------------------------------------------------------------- -- Общие функции -- ---------------------------------------------------------------------------------------------------- -- видим ли мы еще "черный экран" или нет? function black_screen(actor, npc) return device().precache_frame > 1 end --Проверка, встречается ли в имени чувака одна из строк . function check_npc_name (actor , npc , p) if npc:name() == nil then return false end for k,v in pairs(p) do if string.find( npc:name(), v ) then return true end end return false end function check_squad_name (actor , npc , p) local squad = get_object_squad(npc) if not (squad) then return false end local sq for k,v in pairs(p) do sq = get_story_squad(v) if (sq and sq.id == squad.id) then return true end end return false end function is_playing_sound (actor, npc) return xr_sound.sound_table[npc:id()] ~= nil end -- проверка, что актер жив function actor_alive(actor, npc) if db.actor and db.actor:alive() then return true end return false end function see_npc(actor, npc, p) local npc1 = get_story_object(p[1]) if npc and npc1 then --printf("cond : [%s]->[%s]", npc:name(), npc1:name()) return npc:see(npc1) else return false end end function actor_see_npc(actor, npc) return db.actor and db.actor:see(npc) end function npc_in_actor_frustum(actor, npc) return npc_in_actor_frustrum(npc) end function is_wounded(actor, npc) return xr_wounded.is_wounded(npc) end function dist_to_actor_le(actor, npc, p) local d = p[1] if d == nil then printf("Wrong parameter in 'dist_to_actor_le' function!!!") end return d and npc:position():distance_to_sqr(actor:position()) <= tonumber(d)^2 end function dist_to_actor_ge(actor, npc, p) local d = p[1] if d == nil then printf("Wrong parameter in 'dist_to_actor_ge' function!!!") end return d and npc:position():distance_to_sqr(actor:position()) >= tonumber(d)^2 end -- проверка того что npc находится в заданной зоне -- !!! ВЫЗЫВАТЬ ТОЛЬКО ИЗ SPACE RESTRICTOR !!! -- параметры: [sid1:sid2:...] -- !!! НЕКОРРЕКТНО РАБОТАЕТ ДЛЯ ОБЬЕКТОВ В offline'e !!! -- !!! ДЛЯ ГАРАНТИИ ИСПОЛЬЗОВАТЬ one_obj_in_zone !!! function obj_in_zone(actor, zone, p) local sim = alife() for i, v in pairs(p) do local id = get_story_object_id(v) local se_obj = id and alife():object_by_id(id) if se_obj and zone:inside(se_obj.position) then return true end end return false end -- checks if any npc who has jobs at a given smart is in a given zone -- param 1 - smart name -- param 2 - zone name function check_npc_from_gulag_in_zone(actor,npc,p) local smart = p[1] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end local zone = p[2] and db.zone_by_name[p[2]] if not (zone) then return false end for id,se_obj in pairs(smart.npc_info) do if (se_obj.position and zone:inside(se_obj.position)) then return true end end return false end -- параметры: [sid:def*] def=true|false -- * параметр не обязателен function one_obj_in_zone(actor, zone, p) --local def_offline = (p[2] ~= "false") -- default (true) result if npc in offline local id = get_story_object_id(p[1]) local se_obj = id and alife_object(id) if se_obj then -- npc is online return zone:inside(se_obj.position) else -- npc is offline return (p[2] ~= "false") -- default (true) result if npc in offline end end function story_obj_in_zone_by_name (actor, npc, p) local id = get_story_object_id(p[1]) local se_obj = id and alife_object(id) local zone = db.zone_by_name[p[2]] if se_obj and zone then -- npc is online return zone:inside(se_obj.position) end return false end function actor_inside_me(actor,zone,p) return zone:inside(actor:position()) end function actor_in_zone(actor, npc, p) if not (db.actor) then return false end for i=1,#p do local zone = db.zone_by_name[p[i]] if (zone and zone:inside(db.actor:position())) then return true end end return false end function actor_inside_zone(actor, npc, p) if not (db.actor) then return false end for i=1,#p do if db.actor_inside_zones[p[i]] then return true end end return false end function actor_near_smart(actor, npc, p) if not (db.actor) then return false end if not (p and p[1]) then return false end local dist = p[2] and tonumber(p[2]) or 50 local smart = SIMBOARD.smarts_by_names[p[1]] if smart and smart.online then local smrt = SIMBOARD.smarts[smart.id] if smrt and (db.actor:position():distance_to(smart.position) < dist) then return true end end return false end function actor_out_zone(actor, npc, p) return not utils_obj.npc_in_zone(db.actor, p[1]) end function npc_in_zone(actor, npc, p) if not (npc and type(npc.position) == "function") then return false end for i=1,#p do local zone = db.zone_by_name[p[i]] if (zone and zone:inside(npc:position())) then return true end end return false end -- true, если здоровье npc <= заданному значению -- false в противном случае function health_le(actor, npc, p) return p[1] and npc.health < p[1] end -- true, если здоровье актера <= заданному значению -- false в противном случае function actor_health_le(actor, npc, p) return p[1] and actor.health < p[1] end -- true, если здоровье вертолёта <= заданному значению -- false в противном случае function heli_health_le(actor, obj, p) return p[1] and obj:get_helicopter():GetfHealth() < p[1] end -- видит ли вертолёт npc (по story id) function heli_see_npc(actor, obj, p) if p[1] then local o = get_story_object( p[1] ) return o ~= nil and obj:get_helicopter():isVisible( o ) else return false end end function heli_see_actor(actor, obj) return actor ~= nil and obj:get_helicopter():isVisible( actor ) end function gulag_state(actor, npc, p) if xr_gulag.getGulagState(p[1]) == p[2] then return true end return false end function npc_community(actor, npc, p) local npc_obj if p[1] == nil then printf("Wrong number of params in npc_community") end if type(npc.id) ~= "function" then npc_obj = db.storage[npc.id] and db.storage[npc.id].object if npc_obj == nil then return npc:community() == p[1] end else npc_obj = npc end if character_community(npc_obj) == p[1] then return true end return false end function npc_rank(actor, npc, p) if p[1] == nil then printf("Wrong number of params in npc_rank") end if ranks.get_obj_rank_name(npc) == p[1] then return true end return false end function npc_profile(actor, npc, p) if p[1] == nil then printf("Wrong number of params in npc_profile") end if npc:profile_name() == p[1] then return true end return false end -- Проверка того что удар был нанесен кем-то из npc указанных в списке. -- Параметры это story_id персонажей. Можно задавать несколько story_id. function hitted_by(actor, npc, p) local npc1 local t = db.storage[npc:id()].hit if t then for i, v in pairs(p) do npc1 = get_story_object(v) if npc1 and t.who == npc1:id() then return true end end end return false end -- Функция проверки попадания в кость по её индексу.(Проверка только для секции hit) function hitted_on_bone(actor, npc, p) for k,v in pairs (p) do if db.storage[npc:id()].hit.bone_index == npc:get_bone_id(v) then return true end end return false end -- Проверка, что лучшее оружие персонажа - пистолет function best_pistol(actor, npc) local pistol = npc:item_in_slot(1) if pistol ~= nil then return true else return false end end -- Проверка, что персонажу нанесли смертельный хит. Проверять ТОЛЬКО на on_hit function deadly_hit(actor, npc) if db.storage[npc:id()] == nil or db.storage[npc:id()].hit == nil then --printf("deadly hit false") return false end --printf("deadly hit [%s]", tostring(db.storage[npc:id()].hit.deadly_hit == true)) return db.storage[npc:id()].hit.deadly_hit == true end -- Проверка того что персонаж был убит кем-то из npc указанных в списке. -- Параметры это story_id персонажей. Можно задавать несколько story_id. function killed_by(actor, npc, p) local npc1 local t = db.storage[npc:id()].death if t then for i, v in pairs(p) do npc1 = get_story_object(v) if npc1 and t.killer == npc1:id() then --printf("_bp: killed_by(%d)", v) return true end end end return false end -- проверка (по story_id) все ли проверяемые сталкеры живы -- TODO: исправить ситуацию, когда выдается неправильный результат для обьектов, которые -- не успели проспавниться. function is_alive_all(actor, npc, p) local sim = alife() for i, v in pairs(p) do local id = get_story_object_id(v) local se_obj = id and sim:object(id) if se_obj and (not IsStalker(nil,se_obj:clsid()) or not se_obj:alive()) then return false end end return true end -- проверка (по story_id) того, что чотя бы один из проверяемых сталкеров жив -- TODO: исправить ситуацию, когда выдается неправильный результат для обьектов, которые -- не успели проспавниться. function is_alive_one(actor, npc, p) local sim = alife() for i, v in pairs(p) do local id = get_story_object_id(v) local se_obj = id and sim:object(id) if se_obj and IsStalker(nil,se_obj:clsid()) and se_obj:alive() then return true end end return false end -- Modified by DoctorX -- Description: Determines whether or not a npc is alive -- Usage: is_alive( p[1] ) -- Parameters: -- p[1] (type: string) ID of the NPC to check -- Return value (type: bool): Returns true if the npc is alive, false otherwise -- Check if NPC is alive: function is_alive( actor, npc, p ) local npc1 if npc == nil or (p and p[1]) then npc1 = get_story_object_id( p[1] ) elseif ( type( npc.id ) == "number" ) then npc1 = npc.id else npc1 = npc:id( ) end if npc1 == nil then return false end npc1 = alife( ):object( npc1 ) if npc1 and IsStalker( npc1 ) and npc1:alive( ) then return true end return false end -- проверка (по story_id) все ли проверяемые сталкеры мертвы -- TODO: исправить ситуацию, когда выдается неправильный результат для обьектов, которые -- не успели проспавниться. function is_dead_all(actor, npc, p) local npc1 for i, v in pairs(p) do npc1 = get_story_object(v) if npc1 then if npc1:alive() then return false else --printf("_bp: is_dead_all(%d) = true", v) return true end end return false end return true end -- проверка (по story_id) того, что хотя бы один из проверяемых сталкеров мертв -- TODO: исправить ситуацию, когда выдается неправильный результат для обьектов, которые -- не успели проспавниться. function is_dead_one(actor, npc, p) local npc1 for i, v in pairs(p) do npc1 = get_story_object(v) if not npc1 or not npc1:alive() then --printf("_bp: is_dead_one(%d) = true", v) return true end end return false end -- проверка (по story_id) того, что хотя бы один из проверяемых сталкеров мертв -- TODO: исправить ситуацию, когда выдается неправильный результат для обьектов, которые -- не успели проспавниться. function is_dead(actor, npc, p) local npc1 = get_story_object(p[1]) return not (npc1 and npc1:alive()) end -- Проверяет , существует ли обьект с заданным стори айди. function story_object_exist(actor, npc, p) local npc1 = get_story_object(p[1]) return npc1 ~= nil end --[[ -- проверка (по story_id) того, что нашим врагом есть хотя бы кото-то один из списка function check_fighting(actor, npc, p) local enemy_id = db.storage[npc:id()].enemy_id local enemy = db.storage[enemy_id] and db.storage[enemy_id].object local sid if enemy and enemy:alive() then sid = enemy:story_id() for i, v in pairs(p) do --printf("_bp: %s.check_fighting(%d)", npc:name(), v) if type(v) == 'number' and sid == v then --printf("TRUE") return true end end end --printf("_bp: check_fighting() = false") return false end ]]-- -- true, если у актёра в инвентаре есть указанный предмет -- false, если нету, либо не задана секция предмета function actor_has_item(actor, npc, p) return p[1] ~= nil and db.actor:object( p[1] ) ~= nil end function actor_has_item_amount(actor, npc, p) local cnt = p[1] and utils_item.get_amount(db.actor, p[1]) or 0 local amt = p[2] and tonumber(p[2]) return amt and (cnt >= amt) end function npc_has_item(actor, npc, p) return p[1] ~= nil and npc:object( p[1] ) ~= nil end -- проверяет наличие заданого количества предметов в инвентаре игрока. function actor_has_item_count(actor, npc, p) local item_section = p[1] local need_count = tonumber(p[2]) local has_count = 0 local function calc(temp, item) --printf("item [%s]",tostring(item:section())) if item:section() == item_section then has_count = has_count + 1 end end actor:iterate_inventory(calc, actor) return has_count >= need_count end -- возвращает true, если в текущей схеме персонажа взведён указанный сигнал. function signal(actor, npc, p) if p[1] then local st = db.storage[npc:id()] local sigs = st[st.active_scheme].signals -- printf( "xr_conditions.signal: npc=%s, scheme=%s", npc:name(), tostring(st.active_scheme) ) return sigs ~= nil and sigs[p[1]] == true else return false end end -- возвращает true, если значение указанного счётчика актёра больше указанного числа function counter_greater(actor, npc, p) if p[1] and p[2] then local c = load_var(actor, p[1], 0) -- if c > p[2] then printf("pl: counter [%s] greater [%s]", p[1], p[2]) end return c > p[2] else return false end end function counter_equal(actor, npc, p) if p[1] and p[2] then local c = load_var(actor, p[1], 0) return c == p[2] else return false end end --[[ -- определяет нечётность интервала игрового времени. интервал нужно передать в p[1] function odd_time_interval(actor, npc, p) return odd( game.time() / p[1] ) end ]]-- ------------------------------------------------------------------------------------------------------- -- Функции поддержки kamp function _kamp_talk(actor, npc) if xr_kamp.kamp_stalkers[npc:id()] then return xr_kamp.kamp_stalkers[npc:id()] end return false end function _used(actor, npc) return npc:is_talking() end ------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------- -- Функции поддержки безопасности баз function check_smart_alarm_status(actor, npc, p) local smart = p[1] and SIMBOARD:get_smart_by_name(p[1]) return smart and smart:check_alarm() or false end ------------------------------------------------------------------------------------------------------- function has_enemy(actor, npc) local be = npc:best_enemy() return be and be:alive() or false end function has_actor_enemy(actor, npc) local best_enemy = npc:best_enemy() return db.actor and best_enemy ~= nil and best_enemy:id() == AC_ID end function see_enemy(actor, npc) local enemy = npc:best_enemy() if enemy ~= nil then return npc:see(enemy) end return false end function has_enemy_in_current_loopholes_fov(actor, npc) return npc:in_smart_cover() and npc:best_enemy() ~= nil and npc:in_current_loophole_fov( npc:best_enemy():position()) or false end function talking(actor, npc) return actor:is_talking() end function npc_talking(actor, npc) return npc:is_talking() end function see_actor(actor, npc) return npc:alive() and npc:see(actor) end ------------------------------------- function actor_enemy(actor, npc) local t = db.storage[npc:id()].death return npc:relation(actor) >= game_object.enemy or (t ~= nil and t.killer == actor:id()) end function actor_friend(actor, npc) return npc:relation(actor) == game_object.friend end function actor_neutral(actor, npc) return npc:relation(actor) == game_object.neutral end ------------------------------------- -- TODO: these functions have been used to avoid special npcs dying once player disguise as an enemy faction -- However, another issue raised, shooting these npcs don't do anything anymore. Find a way to make special characters die if actor is shooting them or he's a true enemy function actor_true_enemy(actor, npc) local t = db.storage[npc:id()].death return npc:relation(actor) >= game_object.enemy or (t ~= nil and t.killer == actor:id()) --local comm_actor = get_actor_true_community() or "none" --local comm_npc = npc and character_community(npc) or "none" --return game_relations.is_factions_enemies(comm_actor, comm_npc) end function actor_true_friend(actor, npc) return npc:relation(actor) == game_object.friend --local comm_actor = get_actor_true_community() or "none" --local comm_npc = npc and character_community(npc) or "none" --return game_relations.is_factions_friends(comm_actor, comm_npc) end function actor_true_neutral(actor, npc) return npc:relation(actor) == game_object.neutral --local comm_actor = get_actor_true_community() or "none" --local comm_npc = npc and character_community(npc) or "none" --return game_relations.is_factions_neutrals(comm_actor, comm_npc) end ------------------------------------- function is_factions_enemies(actor, npc, p) if(p[1] and p[2]) then return game_relations.is_factions_enemies(p[1], p[2]) else return false end end function is_factions_neutrals(actor, npc, p) return not(is_factions_enemies(actor, npc, p) or is_factions_friends(actor, npc, p)) end function is_factions_friends(actor, npc, p) if(p[1] and p[2]) then return game_relations.is_factions_friends(p[1], p[2]) else return false end end ------------------------------------- function is_faction_enemy_to_actor(actor, npc, p) if(p[1]~=nil) then -- return db.actor:community_goodwill(p[1])<-1000 return db.actor and relation_registry.community_goodwill(p[1], AC_ID)<=-1000 else return false end end function is_faction_friend_to_actor(actor, npc, p) if(p[1]~=nil) then -- return db.actor:community_goodwill(p[1])>1000 return db.actor and relation_registry.community_goodwill(p[1], AC_ID)>=1000 else return false end end function is_faction_neutral_to_actor(actor, npc, p) return not(is_faction_enemy_to_actor(actor, npc, p) or is_faction_friend_to_actor(actor, npc, p)) end ------------------------------------- function is_squad_friend_to_actor(actor, npc, p) if(p[1]~=nil) then -- printf("squad check goodwill1 [%s]", p[1]) return game_relations.check_all_squad_members(p[1], "friend") else -- printf("squad check goodwill5 [%s]", p[1]) return false end end function is_squad_enemy_to_actor(actor, npc, p) if not p then printf("Not enough arguments in 'is_squad_enemy_to_actor' funciton!") end for k,v in pairs(p) do -- printf("squad check goodwill1 [%s]", v) if game_relations.check_all_squad_members(v, "enemy") then return true end end return false end function is_squad_neutral_to_actor(actor, npc, p) return not(is_squad_enemy_to_actor(actor, npc, p) or is_squad_friend_to_actor(actor, npc, p)) end -- check if actor is enemy to a specific faction (p[1]] function is_actor_enemy_to_faction(actor,npc,p) if(p[1]~=nil) then return game_relations.is_factions_enemies(character_community(db.actor), p[1]) else return false end end -- текущий враг актёр? function fighting_actor(actor, npc) local enemy_id = db.storage[npc:id()].enemy_id local enemy = db.storage[enemy_id] and db.storage[enemy_id].object return enemy and enemy:id() == actor:id() or false end function hit_by_actor(actor, npc) local t = db.storage[npc:id()].hit local hit_by_actor = (t ~= nil and t.who == actor:id()) return hit_by_actor end function killed_by_actor(actor, npc) local t = db.storage[npc:id()].death local killed_by_actor = t ~= nil and t.killer == actor:id() return killed_by_actor end function actor_has_weapon (actor, npc) local obj = actor:active_item() if (obj and IsWeapon(obj)) then return true end return false end function actor_is_safemode(actor, npc) return game.actor_weapon_lowered() end function actor_active_detector(actor, npc, p) local detector_section = p and p[1] if detector_section == nil then printf("Wrong parameters in function 'actor_active_detector'") end local actor_detector = db.actor and db.actor:active_detector() return (actor_detector ~= nil) and actor_detector:section() == detector_section end function heavy_wounded(actor, npc) return xr_wounded.is_heavy_wounded_by_id( npc:id() ) end --[[ Проверка на заданный период времени Время задается в минутах Параметры: (time_shift:period_min) time_shift - периодичность срабатывания period - период срабатывания на котором мы получаем true Примеры: time_period(60:10) - возвращает true каждый час на протяжении первых 10 минут --]] function time_period(actor, npc, p) local tshift, period = p[1], p[2] if tshift ~= nil and period ~= nil and db.actor ~= nil then return tshift > period and level.get_time_minutes() % tshift <= period end return false end function is_rain (actor, npc) return db.actor ~= nil and level.rain_factor() > 0 end function is_heavy_rain (actor, npc) return db.actor ~= nil and level.rain_factor() >= 0.5 end function is_day (actor, npc) return db.actor ~= nil and level.get_time_hours() >= 6 and level.get_time_hours() < 21 end function is_dark_night (actor, npc) return db.actor ~= nil and (level.get_time_hours() < 3 or level.get_time_hours() > 22) end function is_night (actor, npc) return db.actor ~= nil and (level.get_time_hours() < 5 or level.get_time_hours() > 19) end function is_jup_a12_mercs_time (actor, npc) return db.actor ~= nil and (level.get_time_hours() >= 1 and level.get_time_hours() < 5) end function zat_b7_is_night (actor, npc) return db.actor ~= nil and (level.get_time_hours() >= 23 or level.get_time_hours() < 5) end function zat_b7_is_late_attack_time (actor, npc) return db.actor ~= nil and (level.get_time_hours() >= 23 or level.get_time_hours() < 9) end function mob_has_enemy(actor, npc) -- return false if npc == nil then return false end --if npc:get_enemy () then printf ("ENEMY PRESENT") else printf ("ENEMY NOT PRESENT") end return npc:get_enemy() ~= nil end function mob_was_hit(actor, npc) local h = npc:get_monster_hit_info() if h.who and h.time ~= 0 then return true end return false end function actor_on_level(actor, npc, p) for k,v in pairs (p) do --printf("level name: [%s], needed level name: [%s]", level.name(), v`) if v == level.name() then return true end end return false end function npc_on_level(actor, npc, p) local sim = alife() local se_obj = p[1] and npc and (type(npc.id) == "function" and sim:object(npc:id()) or npc) if not (se_obj) then return false end local gg = game_graph() if (sim:level_name(gg:vertex(se_obj.m_game_vertex_id):level_id()) == p[1]) then return true end return false end function treasure_exist(actor, npc, p) --printf("%s %s", actor:name(), npc:name()) return true end --[[ --'----------------------------------------------------------------------------------- --' Cover support --'----------------------------------------------------------------------------------- --' Если возвращает true, то солдаты за каверами начинают стрелять. function cover_attack(actor, npc) --' Берем сквад объекта local squad = get_object_squad(npc) if squad == nil then return false end return squad:cover_attack() end ]]-- --'----------------------------------------------------------------------------------- --' Squad support --'----------------------------------------------------------------------------------- function squad_in_zone(actor, npc, p) local story_id = p[1] local zone_name = p[2] if story_id == nil then printf("Insufficient params in squad_in_zone function. story_id[%s], zone_name[%s]", tostring(story_id), tostring(zone_name)) end if zone_name == nil then zone_name = npc:name() end local sim_board = SIMBOARD local squad = get_story_squad(story_id) if squad == nil then --printf("There is no squad with id[%s]", tostring(squad_id)) return false end local zone = db.zone_by_name[zone_name] if zone == nil then --printf("There is no squad with id[%s]", tostring(zone_name)) return false end local sim = alife() for k in squad:squad_members() do local se_obj = k.id and sim:object(k.id) if (se_obj and zone:inside(se_obj.position)) then return true end end return false end function squad_has_enemy(actor, npc, p) local story_id = p[1] if story_id == nil then printf("Insufficient params in squad_has_enemy function. story_id [%s]", tostring(story_id)) end local squad = get_story_squad(story_id) if squad == nil then --printf("There is no squad with id[%s]", tostring(story_id)) return false end local obj_by_id = level.object_by_id for k in squad:squad_members() do local npc_obj = k.id and object_by_id(k.id) if (npc_obj and npc_obj:best_enemy() ~= nil) then return true end end return false end -- Functions for Yantar function squad_in_zone_all(actor, npc, p) local story_id = p[1] local zone_name = p[2] if story_id == nil or zone_name == nil then printf("Insufficient params in squad_in_zone_all function. story_id[%s], zone_name[%s]", tostring(story_id), tostring(zone_name)) end local squad = get_story_squad(story_id) if squad == nil then --printf("There is no squad with id[%s]", tostring(story_id)) return false end local zone = db.zone_by_name[zone_name] if zone == nil then --printf("There is no squad with id[%s]", tostring(zone_name)) return false end local sim = alife() for k in squad:squad_members() do local se_obj = k.object or k.id and sim:object(k.id) if (se_obj and zone:inside(se_obj.position)) then return true end end return true end function squads_in_zone_b41(actor, npc, p) local smart = SIMBOARD:get_smart_by_name("jup_b41") local zone = db.zone_by_name["jup_b41_sr_light"] local al = alife() if zone == nil then return false end if smart == nil then return false end for k,v in pairs(SIMBOARD.smarts[smart.id].squads) do local squad = alife_object(k) if squad then for j in squad:squad_members() do if not zone:inside(j.object.position) then return false end end end end return true end function squads_in_zone_yan_smart_terrain_6_4(actor, npc, p) local smart = SIMBOARD:get_smart_by_name("yan_smart_terrain_6_4") local zone = db.zone_by_name["yan_smart_terrain_6_4_sr_light"] local al = alife() if zone == nil then return false end if smart == nil then return false end for k,v in pairs(SIMBOARD.smarts[smart.id].squads) do local squad = alife_object(k) if squad then for j in squad:squad_members() do if not zone:inside(j.object.position) then return false end end end end return true end --' Проверка в таргет кондлисте задания, соответствует ли имя сквада переданному function target_squad_name(actor, obj, p) if p[1] == nil then printf("Wrong parameters") end if not(obj) then return false end --callstack() if IsStalker(obj) or IsMonster(obj) then local squad = obj.group_id and obj.group_id ~= 65535 and alife_object(obj.group_id) if not (squad) then return false end if string.find( squad:section_name(), p[1] ) ~= nil then return true end --return alife_object(obj.group_id):section_name() == p[1] end return obj:section_name() == p[1] end --' Проверка в таргет кондлисте задания, соответствует ли имя смарта переданному function target_smart_name(actor, smart, p) if p[1] == nil then printf("Wrong parameters") end --callstack() return smart:name() == p[1] end --' Проверяет жив ли отряд с указанным ID function squad_exist(actor, npc, p) local story_id = p[1] if story_id == nil then printe("Wrong parameter story_id[%s] in squad_exist function", tostring(story_id)) end local squad = get_story_squad(story_id) -- if squad == nil then -- return false -- end return squad ~= nil -- return squad.squad_power > 0 end local cache_squad_smart = {} function squad_name_exist(actor, npc, p) local squad_sec = p[1] local smart_id = cache_squad_smart[squad_sec] if (not smart_id) then if (squad_sec == nil) or (squad_sec and not ini_sys:section_exist(squad_sec)) then printe("~ERROR squad_name_exist | section [%s] doesn't exist in system_ini", tostring(story_id)) end local smart_name = ini_sys:r_string_ex(squad_sec,"target_smart") local smart = smart_name and SIMBOARD.smarts_by_names[smart_name] if smart then smart_id = smart.id cache_squad_smart[squad_sec] = smart_id else printf("~WARNING squad_name_exist | cant' get smart obeject [%s]", smart_name) end end local smrt = smart_id and SIMBOARD.smarts[smart_id] if smrt then for id,_ in pairs(smrt.squads) do local squad = alife_object(id) if squad and (squad:section_name() == squad_sec) then --printf("- squad_name_exist | smart [%s] squad [%s]", ini_sys:r_string_ex(squad_sec,"target_smart"),squad_sec) return true end end end --printf("~ squad_name_exist | squad [%s]",squad_sec) return false end function is_squad_commander(actor, npc) if (type(npc.id) == "number") then npc_id = npc.id else npc_id = npc:id() end local squad = get_object_squad(npc) return squad and squad:commander_id() == npc_id or squad == nil end function squad_npc_count_ge(actor, npc, p) local story_id = p[1] if story_id == nil then printf("Wrong parameter squad_id[%s] in 'squad_npc_count_ge' function", tostring(squad_id)) end local squad = get_story_squad(story_id) if squad then return squad:npc_count() > tonumber(p[2]) else return false end end function surge_complete() if (psi_storm_manager and psi_storm_manager.is_loaded()) then if not (psi_storm_manager.is_finished()) then return false end end if (surge_manager and surge_manager.is_loaded()) then return surge_manager.is_finished() end return true end function surge_started() if (psi_storm_manager and psi_storm_manager.is_loaded() and psi_storm_manager.is_started()) then return true end if (surge_manager and surge_manager.is_loaded() and surge_manager.is_started()) then return true end return false end function surge_kill_all() return surge_manager and surge_manager.is_killing_all() or false end function signal_rocket_flying(actor, npc, p) if p==nil then printf("Signal rocket name is not set!") end if db.signal_light[p[1]] then return db.signal_light[p[1]]:is_flying() else printf("No such signal rocket: [%s] on level", tostring(p[1])) end return false end function quest_npc_enemy_actor(actor, npc, p) if p[1] == nil then printf("wrong story id") else local obj = get_story_object(p[1]) if obj and IsStalker(obj) then if db.actor and obj:general_goodwill(db.actor)<=-1000 then return true end end end return false end function animpoint_reached(actor, npc) local animpoint_storage = db.storage[npc:id()].animpoint if animpoint_storage == nil then return false end local animpoint_class = animpoint_storage.animpoint return animpoint_class:position_riched() end --[[ function npc_stay_offline(actor, npc, p) if p == nil then printf("Wrong parameter!!!") end if npc and db.actor then if is_smart_in_combat(actor, npc, p) then if npc.position:distance_to(db.actor:position())>=30 or game_relations.get_gulag_relation_actor(p[1], "enemy") then return true end end end return false end ]]-- -- проверка того что дистанция до обьекта >= заданной -- параметры: [sid,dist] function distance_to_obj_ge(actor, npc, p) local npc_id = get_story_object_id(p[1]) local npc1 = npc_id and alife_object(npc_id) if npc1 then return db.actor ~= nil and db.actor:position():distance_to_sqr(npc1.position) >= p[2]*p[2] end return false end function distance_to_obj_le(actor, npc, p) local npc_id = get_story_object_id(p[1]) local npc1 = npc_id and alife_object(npc_id) if npc1 then return db.actor ~= nil and db.actor:position():distance_to_sqr(npc1.position) < p[2]*p[2] end return false end function in_dest_smart_cover(actor, npc, p) return npc:in_smart_cover() end function active_item(actor, npc, p) if p and p[1] then for k,v in pairs(p) do if actor:item_in_slot(3) ~= nil and actor:item_in_slot(3):section() == v then return true end end end return false end function actor_nomove_nowpn() local itm = db.actor ~= nil and db.actor:active_item() if not (itm) then return true end if not (IsWeapon(itm)) then return true end if (db.actor:is_talking()) then return true end return false end function jup_b16_is_zone_active(actor, npc) return has_alife_info(npc:name()) end --Функция проверки состояния видимости кровососа. -- Возможный набор параметров --> story_id:visibility_state(можно вызывать откуда угодно) или visibility_state(если вызывается из кастомдаты кровососа) -- visibility_state --> -- 0 - невидимый -- 1 - полувидимый -- 2 - полностью видимый function check_bloodsucker_state(actor, npc, p) if (p and p[1]) == nil then printf("Wrong parameters in function 'check_bloodsucker_state'!!!") end local state = p[1] if p[2] ~= nil then state = p[2] npc = get_story_object(p[1]) end if npc ~= nil then return npc:get_visibility_state () == tonumber(state) end return false end function dist_to_story_obj_ge(actor, npc, p) local id = db.actor and p and get_story_object_id(p[1]) local se_obj = id and alife_object(id) return se_obj and se_obj.position:distance_to(db.actor:position()) > tonumber(p[2]) or false end function dist_to_story_obj_le(actor, npc, p) local id = db.actor and p and get_story_object_id(p[1]) local se_obj = id and alife_object(id) return se_obj and se_obj.position:distance_to(db.actor:position()) < tonumber(p[2]) or false end function actor_has_nimble_weapon(actor, npc) local need_item = {} need_item["wpn_groza_nimble"] = true need_item["wpn_desert_eagle_nimble"] = true need_item["wpn_fn2000_nimble"] = true need_item["wpn_g36_nimble"] = true need_item["wpn_protecta_nimble"] = true need_item["wpn_mp5_nimble"] = true need_item["wpn_sig220_nimble"] = true need_item["wpn_spas12_nimble"] = true need_item["wpn_usp_nimble"] = true need_item["wpn_vintorez_nimble"] = true need_item["wpn_svu_nimble"] = true need_item["wpn_svd_nimble"] = true for k,v in pairs(need_item) do if actor:object(k) ~= nil then return true end end return false end function actor_has_active_nimble_weapon(actor, npc) local need_item = {} need_item["wpn_groza_nimble"] = true need_item["wpn_desert_eagle_nimble"] = true need_item["wpn_fn2000_nimble"] = true need_item["wpn_g36_nimble"] = true need_item["wpn_protecta_nimble"] = true need_item["wpn_mp5_nimble"] = true need_item["wpn_sig220_nimble"] = true need_item["wpn_spas12_nimble"] = true need_item["wpn_usp_nimble"] = true need_item["wpn_vintorez_nimble"] = true need_item["wpn_svu_nimble"] = true need_item["wpn_svd_nimble"] = true if actor:item_in_slot(1) ~= nil and need_item[actor:item_in_slot(1):section()] == true then return true end if actor:item_in_slot(2) ~= nil and need_item[actor:item_in_slot(2):section()] == true then return true end if actor:item_in_slot(3) ~= nil and need_item[actor:item_in_slot(3):section()] == true then return true end return false end function jup_b202_inventory_box_empty(actor, npc) local inv_box = get_story_object("jup_b202_actor_treasure") return inv_box:is_inv_box_empty() end --[[ function jup_b46_actor_has_active_science_detector(actor, npc) if actor:item_in_slot(9) ~= nil and actor:item_in_slot(9):section() == "detector_scientific" then return true end return false end ]]-- function is_in_danger(actor, npc, p) if p and p[1] then npc = get_story_object(p[1]) end --printf("npc: [%s] is in danger [%s]", tostring(npc:id()), tostring(db.storage[npc:id()].danger_flag)) return db.storage[npc:id()].danger_flag end function object_exist(actor , npc , p) return get_story_object(p[1]) ~= nil end function squad_curr_action(actor, npc, p) local squad = get_object_squad(npc) return squad.current_action and squad.current_action == p[1] end function is_monster_snork(actor, npc) return npc:clsid() == clsid.snork_s end function is_monster_dog(actor, npc) return npc:clsid() == clsid.dog_s end function is_monster_psy_dog(actor, npc) return npc:clsid() == clsid.psy_dog_s end function is_monster_polter(actor, npc) return npc:clsid() == clsid.poltergeist_s end function is_monster_tushkano(actor, npc) return npc:clsid() == clsid.tushkano_s end function is_monster_burer(actor, npc) return npc:clsid() == clsid.burer_s end function is_monster_controller(actor, npc) return npc:clsid() == clsid.controller_s end function is_monster_flesh(actor, npc) return npc:clsid() == clsid.flesh_s end function is_monster_boar(actor, npc) return npc:clsid() == clsid.boar_s end function dead_body_searching(actor, npc) return actor_menu.dead_body_searching end function jup_b47_npc_online(actor, npc, p) -- printf("function jup_b47_npc_online: story_obj[%s]", tostring(p[1])) local story_obj = get_story_object(p[1]) if story_obj == nil then return false end local obj = alife_object(story_obj:id()) return obj ~= nil end function anomaly_has_artefact(actor, npc, p) local az_name = p and p[1] local af_name = p and p[2] local anomal_zone = db.anomaly_by_name[az_name] if anomal_zone == nil then return false end if anomal_zone.spawned_count < 1 then return false end if af_name == nil then local af_table = {} for k,v in pairs(anomal_zone.artefact_ways_by_id) do local se_obj = alife_object(tonumber(k)) if (se_obj) then af_table[#af_table+1] = se_obj:section_name() end end return true, af_table end for k,v in pairs(anomal_zone.artefact_ways_by_id) do local se_obj = alife_object(tonumber(k)) if (se_obj and se_obj:section_name() == af_name) then return true end end return false end function zat_b29_anomaly_has_af(actor, npc, p) local az_name = p and p[1] local af_name local anomal_zone = db.anomaly_by_name[az_name] if anomal_zone == nil then return false end if anomal_zone.spawned_count < 1 then return false end for i = 16, 23 do if has_alife_info(dialogs_zaton.zat_b29_infop_bring_table[i]) then af_name = dialogs_zaton.zat_b29_af_table[i] break end end for k,v in pairs(anomal_zone.artefact_ways_by_id) do if alife_object(tonumber(k)) and af_name == alife_object(tonumber(k)):section_name() then give_info(az_name) return true end end return false end function jup_b221_who_will_start(actor, npc, p) -- доступные параметры: ability - проверить есть ли доступные темы, choose - выбрать групировку которая начнет перепалку local reachable_theme = {} local faction_table = {} local info_table = { ---------duty [1] = "jup_b25_freedom_flint_gone", [2] = "jup_b25_flint_blame_done_to_duty", [3] = "jup_b4_monolith_squad_in_duty", [4] = "jup_a6_duty_leader_bunker_guards_work", [5] = "jup_a6_duty_leader_employ_work", [6] = "jup_b207_duty_wins", ---------freedom [7] = "jup_b207_freedom_know_about_depot", [8] = "jup_b46_duty_founder_pda_to_freedom", [9] = "jup_b4_monolith_squad_in_freedom", [10] = "jup_a6_freedom_leader_bunker_guards_work", [11] = "jup_a6_freedom_leader_employ_work", [12] = "jup_b207_freedom_wins" } --Составляем таблицу достыпных тем(тлько номера тем). for k,v in pairs(info_table) do if k <= 6 then faction_table[1] = "duty" faction_table[2] = "0" else faction_table[1] = "freedom" faction_table[2] = "6" end if (has_alife_info(v)) and (not has_alife_info("jup_b221_" .. faction_table[1] .. "_main_" .. tostring(k - tonumber(faction_table[2])) .. "_played")) then table.insert(reachable_theme,k) printf("jup_b221_who_will_start: table reachable_theme ------------------------------> [%s]", tostring(k)) end end if (p and p[1]) == nil then printf("No such parameters in function 'jup_b221_who_will_start'") end if tostring(p[1]) == "ability" then return #reachable_theme ~= 0 -- если таблица пуста значит нет доступных тем и ненадо играть сцену elseif tostring(p[1]) == "choose" then ---------Выберем рандомам елемент составленой таблицы и проверим к какой груперовки он пренадлежит :) return reachable_theme[math.random(1, #reachable_theme)] <= 6 -- если меньше 6-ти значит ДОЛГ если больше 6-ти значит СВОБОДА else printf("Wrong parameters in function 'jup_b221_who_will_start'") end end function pas_b400_actor_far_forward(actor, npc) local fwd_obj = get_story_object("pas_b400_fwd") if fwd_obj then if (db.actor and distance_between(fwd_obj, db.actor) > distance_between(fwd_obj, npc)) then return false end else return false end local distance = 70 * 70 local self_dist = npc:position():distance_to_sqr(actor:position()) if self_dist < distance then return false end local squad = get_object_squad(npc) if (squad) then local sim = alife() for k in squad:squad_members() do local se_obj = k.object or k.id and sim:object(k.id) if (se_obj and se_obj.position:distance_to_sqr(actor:position()) < distance) then return true end end end --printf("npc: [%s], actor is far forward - self_dist [%s] distance [%s]", tostring(npc:name()), self_dist, distance) return true end function pas_b400_actor_far_backward(actor, npc) local bwd_obj = get_story_object("pas_b400_bwd") if bwd_obj then if (db.actor and distance_between(bwd_obj, db.actor) > distance_between(bwd_obj, npc)) then return false end else return false end local distance = 70 * 70 local self_dist = npc:position():distance_to_sqr(actor:position()) if self_dist < distance then return false end local squad = get_object_squad(npc) if (squad) then local sim = alife() for k in squad:squad_members() do local se_obj = k.object or k.id and sim:object(k.id) if (se_obj and se_obj.position:distance_to_sqr(actor:position()) < distance) then return true end end end --printf("npc: [%s], actor is far backward - self_dist [%s] distance [%s]", tostring(npc:name()), self_dist, distance) return true end function pri_a28_actor_is_far(actor, npc) local distance = 150 * 150 local squad = get_story_squad("pri_a16_military_squad") for k in squad:squad_members() do local npc_dist = k.object.position:distance_to_sqr(actor:position()) if npc_dist < distance then return false end end return true end function check_enemy_smart(actor , npc , p) local enemy_id = db.storage[npc:id()].enemy_id local enemy = db.storage[enemy_id] and db.storage[enemy_id].object if enemy == nil or enemy_id == alife():actor().id then return false end local enemy_smart = xr_gulag.get_npc_smart(enemy) if (enemy_smart ~= nil) and (enemy_smart:name() == p[1]) then return true end return false end function zat_b103_actor_has_needed_food(actor, npc, p) return (dialogs_zaton.zat_b103_actor_has_needed_food(actor, npc)) or (has_alife_info("zat_b103_merc_task_done")) end function zat_b29_rivals_dialog_precond(actor, npc) local squads_table = { "zat_b29_stalker_rival_default_1_squad", "zat_b29_stalker_rival_default_2_squad", "zat_b29_stalker_rival_1_squad", "zat_b29_stalker_rival_2_squad" } local zones_table = { "zat_b29_sr_1", "zat_b29_sr_2", "zat_b29_sr_3", "zat_b29_sr_4", "zat_b29_sr_5", } local f_squad = false local squad = get_object_squad(npc) if not (squad) then return false end for k,v in pairs(squads_table) do if squad:section_name() == v then f_squad = true break end end if not f_squad then return false end for k,v in pairs(zones_table) do if utils_obj.npc_in_zone(npc, v) then return true end end return false end function polter_ignore_actor(actor, npc) return npc:poltergeist_get_actor_ignore() end function burer_gravi_attack(actor, npc) return npc:burer_get_force_gravi_attack() end function burer_anti_aim(actor, npc) return npc:burer_get_force_anti_aim() end function jup_b202_actor_treasure_not_in_steal(actor, npc) local before = ((not has_alife_info("jup_b52_actor_items_can_be_stolen")) and (not has_alife_info("jup_b202_actor_items_returned"))) local after = (has_alife_info("jup_b52_actor_items_can_be_stolen") and has_alife_info("jup_b202_actor_items_returned")) return (before or after) end function jup_b25_senya_spawn_condition(actor, npc) return (has_alife_info("jup_b16_oasis_found") or has_alife_info("zat_b57_bloodsucker_lair_clear") or has_alife_info("jup_b6_complete_end") or has_alife_info("zat_b215_gave_maps")) and has_alife_info("zat_b106_search_soroka") end function jup_b25_flint_gone_condition(actor, npc) return has_alife_info("jup_b25_flint_blame_done_to_duty") or has_alife_info("jup_b25_flint_blame_done_to_freedom") or has_alife_info("zat_b106_found_soroka_done") end function check_deimos_phase(actor, npc, p) if(p[1] and p[2]) then local obj = db.storage[npc:id()] local delta = sr_deimos.check_intensity_delta(obj) if(p[2]=="increasing" and delta) then return false elseif(p[2]=="decreasing" and not(delta)) then return false end if(p[1]=="disable_bound") then if(p[2]=="increasing") then if not(sr_deimos.check_disable_bound(obj)) then return true end elseif(p[2]=="decreasing") then return sr_deimos.check_disable_bound(obj) end elseif(p[1]=="lower_bound") then if(p[2]=="increasing") then if not(sr_deimos.check_lower_bound(obj)) then return true end elseif(p[2]=="decreasing") then return sr_deimos.check_lower_bound(obj) end elseif(p[1]=="upper_bound") then if(p[2]=="increasing") then if not(sr_deimos.check_upper_bound(obj)) then return true end elseif(p[2]=="decreasing") then return sr_deimos.check_upper_bound(obj) end end end end -------------------------------------------------------------------------------- function actor_in_surge_cover(actor, npc, p) return GetEvent("current_safe_cover") and true or false end function is_door_blocked_by_npc(actor, obj) return obj:is_door_blocked_by_npc() end function has_active_tutorial() return game.has_active_tutorial() end function upgrade_hint_kardan(actor, npc, p) local hint_table = {} local can_upgrade = 0 local tools = (p and tonumber(p[1])) or 0 if not has_alife_info("zat_b3_all_instruments_brought") then if not has_alife_info("zat_b3_tech_instrument_1_brought") and (tools == 0 or tools == 1) then table.insert(hint_table, "st_upgr_toolkit_1") elseif tools == 1 then can_upgrade = can_upgrade + 1 end if not has_alife_info("zat_b3_tech_instrument_2_brought") and (tools == 0 or tools == 2) then table.insert(hint_table, "st_upgr_toolkit_2") elseif tools == 2 then can_upgrade = can_upgrade + 1 end if not has_alife_info("zat_b3_tech_instrument_3_brought") and (tools == 0 or tools == 3) then table.insert(hint_table, "st_upgr_toolkit_3") elseif tools == 3 then can_upgrade = can_upgrade + 1 end else can_upgrade = can_upgrade + 1 end if not has_alife_info("zat_b3_tech_see_produce_62") then if (tools == 1) and not has_alife_info("zat_b3_tech_have_one_dose") then table.insert(hint_table, "st_upgr_vodka") elseif (tools ~= 1) and (not has_alife_info("zat_b3_tech_have_couple_dose")) then table.insert(hint_table, "st_upgr_vodka") else can_upgrade = can_upgrade + 1 end else can_upgrade = can_upgrade + 1 end inventory_upgrades.cur_hint = hint_table return can_upgrade >= 2 end -- AtmosFear Psi Storm function psi_storm_complete() return psi_storm_manager.is_finished() end -- Returns true if calling NPC has the surrender flag to actor function npc_surrendered(actor,npc,p) if not (db.actor) then return false end local st = db.storage[npc:id()] return st and st.victim_surrender == AC_ID or false end -- Returns true if calling NPC has the surrender flag function npc_surrendered_any(actor,npc,p) local st = db.storage[npc:id()] return st and st.victim_surrender >= 0 and st.victim_surrender < 65534 or false end function actor_class(actor,npc,p) return p and p[1] and axr_misery and axr_misery.ActorClass == p[1] or false end function black_road_enabled(actor,npc,p) return axr_misery and axr_misery.MiseryBlackRoad or false end -- Returns true if a squad behavior equals given -- param 1 is player_id (squad behavior, see _g.script) function squad_behavior(actor,npc,p) local se_npc = type(npc.id) == "function" and alife_object(npc:id()) or npc local squad = se_npc and se_npc.parent_id ~= 65535 and alife_object(se_npc.parent_id) return p and p[1] and squad and squad.player_id == p[1] or false end -- Returns true if a anim state equals given -- param 1 is state function anim_state(actor,npc,p) return p and p[1] and state_mgr.get_state(npc) == p[1] or false end -- Returns if a smart is empty -- param 1 is smart name function smart_empty(actor,npc,p) local board = SIMBOARD local smart = p[1] and board.smarts_by_names[p[1]] if not (smart) then return false end local smart_id = smart.id for k,v in pairs(board.smarts[smart_id].squads) do local se_obj = alife_object(k) if (se_obj) then return false end end return true end function npc_squad_has_enemy(actor,npc,p) local squad = get_object_squad(npc) if not (squad) then return false end local o local object_by_id = level.object_by_id for k in squad:squad_members() do o = k.id and object_by_id(k.id) if (o and o:best_enemy()) then return true end end end -- Returns true if a NPC at a certain smart was hit by calling NPC -- param 1 is smart name function hit_by_enemy_on_smart(actor,npc,p) local id = db.storage[npc:id()].hitted_by local who = id and level.object_by_id(id) if (not who or not who:alive()) then return false end local smart = xr_gulag.get_npc_smart(who) return p and p[1] and smart and smart:name() == p[1] or false end function is_upgrading(actor, npc, p) -- pda.upgrade_closed = not pda.upgrade_closed -- return not pda.upgrade_closed return pda.upgrade_closed end --'----------------------------------------------------------------------------------- --' Minigun support --'----------------------------------------------------------------------------------- function is_minigun_see_actor (actor, npc) local mgun = npc:get_car() return mgun:IsObjectVisible(actor) end function is_minigun_see_current_target(actor,npc,p) local st = npc and db.storage[npc:id()] if not (st) then return false end if not (st.ph_minigun) then return false end if (st.ph_minigun.fire_target == nil or st.ph_minigun.fire_target == "") then return false end if (st.ph_minigun.target_obj == nil or not st.ph_minigun.target_obj:alive()) then return false end return npc:get_car():IsObjectVisible(st.ph_minigun.target_obj) end function squad_hit_by_smart(actor,npc,p) local squad = get_object_squad(npc) if not (squad) then return false end local storage = db.storage for k in squad:squad_members() do local who = k.id and storage[k.id] and storage[k.id].hitted_by and storage[storage[k.id].hitted_by] and storage[storage[k.id].hitted_by].object local smart = who and xr_gulag.get_npc_smart(who) if (smart and smart:name() == p[1]) then return true end end return false end function actor_look_away(actor,npc) if not (db.actor) then return false end if (not db.actor:see(npc) or (utils_data.angle_diff(db.actor:direction(), db.actor:position():sub(npc:position()))<90 and npc:position():distance_to(db.actor:position()) > 2.5) or npc:position():distance_to(db.actor:position())>100) then return true end return false end function between_time(actor,npc,p) return in_time_interval(tonumber(p[1]),tonumber(p[2])) or false end function squad_is_monster(actor,squad,p) return is_squad_monster[squad.player_id] == true end function after_first_meet(actor,npc,p) local st = db.storage[npc:id()] if not (st) then return false end return st.after_first_meet == true end function squad_on_actor_map(actor,npc,p) local squad = get_object_squad(npc) if not (squad) then return false end return get_player_level_id() == game_graph():vertex(squad.m_game_vertex_id):level_id() end -- Returns true if squad commander's active section equals param 1 -- param 2 - active section (ie. "logic@walker1") function squad_commander_active_section(actor,npc,p) local squad = p[1] and get_object_squad(npc) local st = squad and squad:commander_id() and db.storage[squad:commander_id()] return st and st.active_section == p[1] or false end -- Returns true if a NPC on a given job has a patrol index equalling given -- param 1 is smart name -- param 2 is job section (ie. "logic@walker_1") in this case omit 'logic@' -- param 3 is index -- param 4 is min allowed radius to patrol point -- param 5 is boolean, returns true if job is empty function job_on_point(actor,npc,p) --printf("~ job_on_point") -- p[1] = smart_name p[2] = logic p[3] = index p[4] = less_than_equal_to Distance p[5] = return true if object is dead or doesn't exist local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] local id = smart and smart.npc_by_job_section["logic@"..p[2]] local st = id and db.storage[id] local obj = st and st.object if not (obj) then --printf("~ job_on_point } no obj , return true") return p[5] == "true" end local index = st and st.active_scheme and st.active_scheme == "beh" and load_var(obj,"path_index",nil) or obj:get_current_point_index() if (p[4] and index == tonumber(p[3])) then if (st and st.active_scheme and st.active_scheme == "beh") then if (axr_beh.am_i_reached(obj)) then --printf("~ job_on_point | am i reached") return true end --printf("~ job_on_point | am i not reached") return false end local path = obj:patrol() local pos = path and patrol(path):point(tonumber(p[3])) local dist = pos and obj:position():distance_to_sqr(pos) --printf("~ job_on_point | dist: %s", dist) return dist <= tonumber(p[4]) end --printf("~ job_on_point | index: %s", index) return index == tonumber(p[3]) end -- Checks if npc distance is less than equal to given patrol point -- param 1 is patrol path name -- param 2 is path index -- param 3 is distance less than equal function dist_to_point_le(actor,npc,p) local pat = p[1] and level.patrol_path_exists(p[1]) and patrol(p[1]) if (pat) then local index = p[2] and tonumber(p[2]) or 0 local dist = npc:position():distance_to_sqr(pat:point(index)) return dist <= tonumber(p[3]) end return false end function beh_reached(actor,npc,p) if p and p[1]then return axr_beh.am_i_reached(npc,tonumber(p[1])) else return axr_beh.am_i_reached(npc) end end -- Returns true if a NPC occupies a given job -- param 1 is smart name -- param 2 is job section (ie. "logic@walker_1") in this case omit 'logic@' -- param 3 is optional check for active_section function obj_on_job(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] local id = smart and smart.npc_by_job_section["logic@"..p[2]] local st = id and db.storage[id] local obj = st and st.object --printf("~obj_on_job | obj=%s",obj and obj:name()) if not (p[3]) then return obj and obj:alive() or false end return st and st.active_section == p[3] or false end -- Returns true if a NPC sees another NPC on a given job -- param 1 is smart name -- param 2 is job section (ie. "logic@walker_1") in this case omit 'logic@' function see_obj_on_job(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] local id = smart and smart.npc_by_job_section["logic@"..p[2]] local obj = id and db.storage[id] and db.storage[id].object return obj and obj:alive() and npc:memory_time(obj) < 5000 or false end -- Returns true if a NPC on a given job is in danger mode -- param 1 is smart name -- param 2 is job section (ie. "logic@walker_1") in this case omit 'logic@' function obj_on_job_danger(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] local id = smart and smart.npc_by_job_section["logic@"..p[2]] local obj = id and db.storage[id] and db.storage[id].object return obj and db.storage[id].danger_flag or false end -- Returns true if a NPC on a given job was hit by calling NPC -- param 1 is smart name -- param 2 is job section (ie. "logic@walker_1") in this case omit 'logic@' function obj_on_job_hit_by(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] local id = smart and smart.npc_by_job_section["logic@"..p[2]] local obj = id and (db.storage[id] and db.storage[id].object or level.object_by_id(id)) if (not obj and not obj:alive()) then return false end local who_id = db.storage[id].hitted_by return who_id and who_id == npc:id() or false end -- Returns true if a NPC's on a given job has a given active section -- param 1 is smart name -- param 2 is job section (ie. "logic@walker_1") in this case omit 'logic@' -- param 3 is active section (ie. "walker@walker_1_surge_1") function job_active_section(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] local id = smart and smart.npc_by_job_section["logic@"..p[2]] local obj = id and (db.storage[id] and db.storage[id].object or level.object_by_id(id)) return obj and db.storage[id].active_section == p[3] or false end -- Returns true if ONLY monster-type NPC's occupy a given smart -- param 1 is smart name function is_only_monsters_on_jobs(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end for id,npc_info in pairs(smart.npc_info) do if (npc_info.stype ~= modules.stype_mobile) then return false end end return true end -- Returns true if ONLY stalkers occuppy a given smart -- param 1 is smart name function is_only_stalkers_on_jobs(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end for id,npc_info in pairs(smart.npc_info) do if (npc_info.stype == modules.stype_mobile or npc_info.stype == modules.stype_heli) then return false end end return true end -- Returns true if ONLY a given community occupies a given smart -- param 1 is smart name function is_only_community_on_jobs(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end for id,npc_info in pairs(smart.npc_info) do if (npc_info.se_obj and (npc_info.stype == 0 or npc_info.stype == 1) and npc_info.se_obj:character_community() ~= p[2]) then return false end end return true end function smart_squad_by_faction_in_radius(actor,npc,p) local smart = p[1] and p[2] and p[3] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end local smrt = SIMBOARD.smarts[smart.id] if not (smrt) then return false end for k,v in pairs(smrt.squads) do local squad = alife_object(k) if (squad and squad.player_id == p[2] and squad.position:distance_to_sqr(smart.position) <= tonumber(p[3])^2) then return true end end return false end -- Returns true if squads by behavior faction (player_id) of a given count exist at smart out of entire population; including arriving -- param1 - smart_name -- param2 - faction aka player_id -- param3 - greater than equal to number function smart_squad_count_ge_by_faction(actor,npc,p) local smart = p[1] and p[2] and p[3] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end local smrt = SIMBOARD.smarts[smart.id] if not (smrt) then return false end local count = 0 for k,v in pairs(smrt.squads) do local squad = alife_object(k) if (squad and squad.player_id == p[2]) then count = count + 1 end end return count >= tonumber(p[4]) end function smart_population_count(actor,npc,p) local smart = p[1] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end return p[2] and SIMBOARD.smarts[smart.id] and SIMBOARD.smarts[smart.id].population == tonumber(p[2]) or false end function smart_population_count_ge(actor,npc,p) local smart = p[1] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end return p[2] and SIMBOARD.smarts[smart.id] and SIMBOARD.smarts[smart.id].population >= tonumber(p[2]) or false end function smart_population_count_le(actor,npc,p) local smart = p[1] and SIMBOARD.smarts_by_names[p[1]] if not (smart) then return false end return p[2] and SIMBOARD.smarts[smart.id] and SIMBOARD.smarts[smart.id].population <= tonumber(p[2]) or false end -- Returns true if any instance of given community occupies a given smart -- param 1 is smart name function is_community_on_jobs(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end for id,npc_info in pairs(smart.npc_info) do if (npc_info.se_obj and (npc_info.stype == 0 or npc_info.stype == 1) and npc_info.se_obj:character_community() == p[2]) then return true end end return false end function is_community_arriving(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end for id,se_obj in pairs(smart.arriving_npc) do if (se_obj and IsStalker(se_obj) and se_obj:character_community() == p[2]) then return true end end return false end function community_arriving_dist_ge(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end local exist for id,se_obj in pairs(smart.arriving_npc) do if (se_obj and IsStalker(se_obj) and se_obj:character_community() == p[2]) then exist = true if (se_obj.position:distance_to_sqr(smart.position) >= tonumber(p[3] or 10000)) then return true end end end -- community does not exist at smart return true if not (exist) then return true end return false end --' SP -- Sidor --------------------------------------- function trade_exchanged(actor, npc) local npc_id = npc:id() return (db.storage[npc_id].mob_trade and db.storage[npc_id].mob_trade.exchanged) --or false end function trading(actor, npc) local npc_id = npc:id() return (db.storage[npc_id].mob_trade and db.storage[npc_id].mob_trade.trading) --or false end function trade_sell_coast_b_1000(actor, npc) return db.storage[npc:id()].mob_trade.sell_coast > 1000 end function trade_sell_coast_b_0_m_1000(actor, npc) return db.storage[npc:id()].mob_trade.sell_coast > 0 and db.storage[npc:id()].mob_trade.sell_coast < 1000 end function trade_buy_coast(actor, npc) return db.storage[npc:id()].mob_trade.buy_coast > 1000 end function trade_all_money(actor, npc) return db.storage[npc:id()].mob_trade.all_money > 2000 end -- Sidor --------------------------------------- --' SP function npc_in_actor_community(actor,npc,p) local comm = character_community(npc) return db.actor and string.find(character_community(db.actor),comm) ~= nil end function actor_community(actor,npc,p) if not (db.actor) then return false end for i=1,#p do if (character_community(db.actor) == p[i]) then return true end end return false end function actor_true_community(actor,npc,p) if not (db.actor) then return false end local actor_comm = get_actor_true_community() for i=1,#p do if (actor_comm == p[i]) then return true end end return false end function actor_goodwill_ge(actor,npc,p) if (p[1] and p[2]) then return db.actor and relation_registry.community_goodwill(p[1], AC_ID) >= tonumber(p[2]) end return false end function task_giver_alive(actor,npc,p) if not (p[1]) then return false end local tm = task_manager.get_task_manager() local tsk = tm.task_info[p[1]] if not (tsk) then return true end local se_obj = tsk.task_giver_id and alife_object(tsk.task_giver_id) if (se_obj) then if (se_obj:clsid() == clsid.online_offline_group_s) then return true -- if squad exist then atleast 1 npc should be alive elseif (se_obj:alive()) then return true end end return false end local cache_weeks = {} -- cache for less usage since a lot of smarts have this condition function actor_week_in_zone(actor,npc,p) if not (p[1]) then return false end if cache_weeks[p[1]] ~= nil then return cache_weeks[p[1]] end local s_time = level.get_start_time() local seconds = tonumber(game.get_game_time():diffSec(s_time)) local days = math.floor(((seconds/60)/60)/24) local weeks = days/7 if (weeks > 10) then weeks = 10 end local result = (weeks >= p[1]) and true or false cache_weeks[p[1]] = result --printf("~ Condition check | actor_week_in_zone | [%s] = %s", p[1], result) return result end function is_a_task_giver(actor,npc,p) local tm = task_manager.get_task_manager() for task_id,tsk in pairs(tm.task_info) do if (tsk.task_giver_id and tsk.task_giver_id == npc:id()) then return true end end return false end -- param1 - smart by name -- param2 - community -- param3 - if true, then it will check_npc_name for that faction (This is used for suitable in logic section) function smart_under_faction_control(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end if not (smart.faction and smart.faction_controlled) then return false end if not (p[2] and smart.faction == p[2]) then return false end if (p[3] and p[3] == "true") then if npc:name() == nil then return false end local f = { ["stalker"] = "stalker", ["bandit"] = "bandit", ["killer"] = "merc", ["dolg"] = "duty", ["freedom"] = "freedom", ["monolith"] = "monolith", ["ecolog"] = "ecolog", ["csky"] = "csky", ["army"] = "military" } if not (f[p[2]]) then return false end if string.find( npc:name(), f[p[2]] ) then return true end else return true end return false end function smart_under_faction_war(actor,npc,p) local board = SIMBOARD local smart = p[1] and board and board.smarts_by_names[p[1]] if not (smart) then return false end return smart.faction_war_in_progress == true end function heli_inside_level_boundary(actor,npc,p) for id,o in pairs(db.heli) do local pos = o:position() local bmin = level.get_bounding_volume().min local bmax = level.get_bounding_volume().max return pos.x >= bmin.x and pos.z >= bmin.z and pos.x <= bmin.x+bmax.x and pos.z <= bmin.z+bmax.z end return false end ------------------------------------------------------------------------------------- -- Special for Radar ------------------------------------------------------------------------------------- function rad_pass_time(actor, npc) return true -- return level.get_time_hours() >= 10 and level.get_time_hours() < 11 end function heli_dist_to_max_bounding_le(actor,npc,p) local heli = npc and npc:get_helicopter() if not (heli) then return false end local d = p[1] and tonumber(p[1]) local dist = d and heli_alife.distance_2d_sqr(npc:position(),level.get_bounding_volume().max) return dist and dist <= d or false end function down_to_earth_functor(actor,npc,p) return game_achievements.has_achievement("down_to_earth") end function heavy_pockets_functor(actor,npc,p) return game_achievements.has_achievement("heavy_pockets") end ------------------------------------------------------------------------------------ -- Special functions for OLD ARENA ------------------------------------------------------------------------------------ function bar_arena_actor_inside(actor,npc) local t = db.zone_by_name["bar_arena_waiter"] if t and db.actor then if t:inside(db.actor:position()) then return true end end return false end function bar_arena_actor_fight(actor,npc) local t = db.zone_by_name["bar_arena_sr"] local tt = db.zone_by_name["bar_arena_waiter"] if t and tt and db.actor then if t:inside(db.actor:position()) and not tt:inside(db.actor:position()) then return true end end return false end function bar_arena_actor_outside(actor,npc) local t = db.zone_by_name["bar_arena_waiter_out"] if t and db.actor then if t:inside(db.actor:position()) then return true end end return false end function actor_dead(actor, npc) if db.actor and not db.actor:alive() then return true end return false end ------------------------------------------------------------------------------------ -- Special functions for NEW ARENA ------------------------------------------------------------------------------------ function bar_actor_rank_stalker (actor,npc) if db.actor and db.actor:character_rank() > 1499 then return true end return false end function bar_actor_rank_veteran (actor,npc) if db.actor and db.actor:character_rank() > 2999 then return true end return false end function bar_arena_fight_3_end (actor,npc) return has_alife_info("bar_arena_fight_3_stalker_1_die") and has_alife_info("bar_arena_fight_3_stalker_2_die") end function bar_arena_fight_4_end (actor,npc) return has_alife_info("bar_arena_fight_4_stalker_1_die") and has_alife_info("bar_arena_fight_4_stalker_2_die") and has_alife_info("bar_arena_fight_4_stalker_3_die") end function bar_arena_fight_5_end (actor,npc) return has_alife_info("bar_arena_fight_5_stalker_1_die") and has_alife_info("bar_arena_fight_5_stalker_2_die") end function bar_arena_fight_6_end (actor,npc) return has_alife_info("bar_arena_fight_6_stalker_1_die") and has_alife_info("bar_arena_fight_6_stalker_2_die") and has_alife_info("bar_arena_fight_6_stalker_3_die") and has_alife_info("bar_arena_fight_6_stalker_4_die") and has_alife_info("bar_arena_fight_6_stalker_5_die") and has_alife_info("bar_arena_fight_6_stalker_6_die") end function bar_arena_fight_8_end (actor,npc) return has_alife_info("bar_arena_fight_8_stalker_1_die") and has_alife_info("bar_arena_fight_8_stalker_2_die") and has_alife_info("bar_arena_fight_8_stalker_3_die") and has_alife_info("bar_arena_fight_8_stalker_4_die") end function heli_exist_on_level(actor,npc) if (is_empty(db.heli)) then return false end return true end function kill_count_ge(actor,npc,p) local count = load_var(db.actor,p[1].."_count") or 0 return count >= tonumber(p[2]) end function any_on_level(actor,npc,faction_list) local found = false local se_actor = alife():actor() for id,v in pairs(SIMBOARD.squads) do local squad = alife_object(id) if (squad) and simulation_objects.is_on_the_same_level(squad, se_actor) then if not (squad.first_update) then return -- not all squads are loaded yet! end if not (squad:get_script_target()) then for i=1,#faction_list do if (faction_list[i] == "monster" and is_squad_monster[squad.player_id]) or (squad.player_id == faction_list[i]) then for k in squad:squad_members() do local member = db.storage[k.id] and db.storage[k.id].object if (member and member:clsid() ~= clsid.bloodsucker_s) then -- only because they stay invis and hard to fight squad.force_online = true found = true break end end end end end end end return found end function is_actor_surge_immuned(actor,npc,p) return load_var(db.actor,"surge_immuned",false) == true end function get_start_time_elapsed_ge(actor,npc,p) return p[1] and tonumber(game.get_game_time():diffSec(level.get_start_time())) >= tonumber(p[1]) end function awr_have_no_info(actor,npc,p) local npc_name = npc:section() if not (db.actor:has_info(string.format('awr_%s_access', npc_name))) then return true end end function base_defense_is_actor_on_level(actor,npc,p) local name = load_var(db.actor,"base_defense_level") if (name) then return name == level.name() end return true end function is_story(actor,npc,p) return npc and get_object_story_id(type(npc.id) == "function" and npc:id() or npc.id) ~= nil end function is_open_routes_mode(actor,npc,p) return alife_storage_manager.get_state().opened_routes end function is_not_open_routes_mode(actor,npc,p) return not alife_storage_manager.get_state().opened_routes end